#include "ExpressionResolutor.h"

#include "SNumber.h"
#include "SStruct.h"
#include "SVector.h"

SValueSp ExpressionResolutor::Resolve(string expression, SValueSpMapSp vars, SType type)
{
	// Literal simple type parsing
	try
	{
		return Utility::SimpleParse(type, expression);
	}
	catch(...) {}

	return Resolve(expression, vars);
}

SValueSp ExpressionResolutor::Resolve(string expression, SValueSpMapSp vars, TypeDescriptorSp td)
{
	// Literal complex type parsing
	try
	{
		return Utility::ComplexParse(td, expression, vars);
	}
	catch(...) {}

	return Resolve(expression, vars);
}

SValueSp ExpressionResolutor::Resolve(string expression, SValueSpMapSp vars)
{
	trim(expression);

	// Type inference
	try
	{
		return Utility::SimpleParse(STypeByte, expression);
	}
	catch(...) {}

	try
	{
		return Utility::SimpleParse(STypeNumber, expression);
	}
	catch(...) {}

	try
	{
		return Utility::SimpleParse(STypeChar, expression);
	}
	catch(...) {}

	try
	{
		return Utility::SimpleParse(STypeString, expression);
	}
	catch(...) {}

	// Variable resolution
	SValueSp tempVar;
	smatch m;

	StringVector tokens;
	split( tokens, expression, is_any_of(".") );

	string member = "";
	string parenthesis = "";

	for(int i=0; i<(int)tokens.size(); ++i)
	{
		trim(tokens[i]);
		string token = tokens[i];
		
		if ( regex_match( token, m, regex("([^\\[\\]]+)(\\[.+)") ))
		{
			member = m[1];
			parenthesis = m[2];
		}
		else
		{
			member = token;
			parenthesis = "";
		}

		// Get the variable or the member of the current temp variable

		if ( !tempVar ) // is the first element
		{
			// Get the variable
			SValueSpMap::iterator it = vars->find(member);
			if ( it == vars->end() )
			{
				// the variable is not defined
				break; 
			}
			
			tempVar = (*vars)[member];			
		}
		else
		{
			// Get the member
			try
			{
				tempVar = tempVar->As<SStruct>()->Get(member);
			}
			catch(...)
			{
				throw SParseException("The expression '" + expression + "' is not valid.");
			}
		}

		// Get indexes
		int p = 0;  // index of the first parenthesis found
		vector<int> indexes;

		for(int j=0; j < (int) parenthesis.length(); ++j)
		{
			if ( parenthesis[j] == '[' ) p = j;

			if ( parenthesis[j] == ']' )
			{
				SNumberSp index = SNumber::Parse( parenthesis.substr(p + 1, j - p - 1) );

				// Get the element in the index position
				try
				{
					tempVar = tempVar->As<SVector>()->Get( index->Get() );
				}
				catch(...)
				{
					throw SParseException("Out of range in the expression.");
				}
			}
		}		
	}

	if ( !tempVar )
	{
		
		throw SParseException("The expression '" + expression + "' is not valid.");
	}

	return tempVar;
}
